import cv2
import mediapipe as mp
import math
class Blink:
    def __init__(self):
        self.face_mesh = mp.solutions.face_mesh.FaceMesh()
        # 左眼关键点序号
        self.FANCEMESH_LEFT_EYE = [362, 385, 387, 263, 373, 380]
        # 右眼关键点序号
        self.FANCEMESH_RIGHT_EYE = [33, 160, 158, 133, 153, 144]
        # 存储人脸关键点
        self.face_landmark = []

    def get_face_landmark(self, frame):
        """
        获取面部网格关键点
        :param frame:
        """
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        result = self.face_mesh.process(frame_rgb)
        multi_face_landmarks = result.multi_face_landmarks
        if multi_face_landmarks is None:
            return
        # 当前处理一张人脸图像
        face_landmarks = multi_face_landmarks[0]
        # 绘制关键点的序号
        landmark = face_landmarks.landmark
        # 将人脸关键点设置为成员变量
        self.face_landmark = landmark
        return face_landmarks

    def draw_style(self, frame, face_landmarks):
        conns = mp.solutions.face_mesh_connections.FACEMESH_LEFT_EYE
        # point_style = mp.solutions.drawing_utils.DrawingSpec(color=(0, 100, 255), thickness=1)
        # line_style = mp.solutions.drawing_utils.DrawingSpec(color=(0, 100, 255), thickness=1)
        # # 绘制样式
        # mp.solutions.drawing_utils.draw_landmarks(
        #     frame,
        #     face_landmarks,
        #     conns,
        #     point_style,
        #     line_style
        # )
        frame_h, frame_w, _ = frame.shape
        for index, lm in enumerate(self.face_landmark):
            if index not in self.FANCEMESH_LEFT_EYE and index not in self.FANCEMESH_RIGHT_EYE:
                continue
            x = round(frame_w * lm.x)
            y = round(frame_h * lm.y)
            cv2.putText(frame, str(index),
                        org=(x - 2, y - 2),
                        fontFace=cv2.FONT_ITALIC,
                        fontScale=0.3,
                        color=(0, 0, 255),
                        thickness=1
                        )

    def cal_EAR(self):
        """
        计算纵横比
        :return:
        """
        p2 = self.index_convert_point(160)
        p6 = self.index_convert_point(144)

        p3 = self.index_convert_point(158)
        p5 = self.index_convert_point(153)

        p1 = self.index_convert_point(33)
        p4 = self.index_convert_point(133)

        #左眼各点位的距离
        dis_p2_6 = self.get_Distance(p2, p6)
        dis_p3_5 = self.get_Distance(p3, p5)
        dis_p1_4 = self.get_Distance(p1, p4)
        #计算纵横比
        EAR_left = (dis_p2_6+dis_p3_5) / (2 * dis_p1_4) * 10
        # print(EAR_left)
        thresh = 2.3
        # 右眼检测
        s1 = self.index_convert_point(362)
        s4 = self.index_convert_point(263)

        s2 = self.index_convert_point(385)
        s6 = self.index_convert_point(380)

        s3 = self.index_convert_point(387)
        s5 = self.index_convert_point(373)

        dis_s2_6 = self.get_Distance(s2, s6)
        dis_s3_5 = self.get_Distance(s3, s5)
        dis_s1_4 = self.get_Distance(s1, s4)

        EAR_right = (dis_s2_6 + dis_s3_5) / (2 * dis_s1_4) * 10
        thresh = 2.0
        print('左眼：'+str(EAR_right)+'\n右眼：'+str(EAR_left))

    def detect(self, frame):
        self.frame = frame
        face_landmarks = self.get_face_landmark(frame)
        # 如果没有检测到关键点直接返回
        if face_landmarks is None:
            return
        self.draw_style(frame, face_landmarks)
        # 计算纵横比
        self.cal_EAR()

    def index_convert_point(self, index):
        h, w, _ = self.frame.shape
        lm = self.face_landmark[index]
        x = round(lm.x * w)
        y = round(lm.y * h)
        return x, y

    def get_Distance(self, p1, p2):
        return math.hypot(p1[0] - p2[0], p1[1] - p2[1])
